package org.zn.note.designpattern;

import java.util.ArrayList;
import java.util.List;

/**
 * 拦截过滤器模式（Intercepting Filter Pattern）
 * <p>
 * 过滤器（Filter） - 过滤器在请求处理程序执行请求之前或之后，执行某些任务。
 * 过滤器链（Filter Chain） - 过滤器链带有多个过滤器，并在 Target 上按照定义的顺序执行这些过滤器。
 * Target - Target 对象是请求处理程序。
 * 过滤管理器（Filter Manager） - 过滤管理器管理过滤器和过滤器链。
 * 客户端（Client） - Client 是向 Target 对象发送请求的对象。
 */
public class Pattern31_InterceptingFilter {

    public static void main(String[] args) {
        FilterManager filterManager = new FilterManager(new Target());
        filterManager.setFilter(new AuthenticationFilter());
        filterManager.setFilter(new DebugFilter());

        Client client = new Client();
        client.setFilterManager(filterManager);
        client.sendRequest("HOME");
    }

    interface Filter {
        void execute(String request);
    }

    private static class AuthenticationFilter implements Filter {
        public void execute(String request) {
            System.out.println("Authenticating request: " + request);
        }
    }

    private static class DebugFilter implements Filter {
        public void execute(String request) {
            System.out.println("request log: " + request);
        }
    }

    private static class Target {
        void execute(String request) {
            System.out.println("Executing request: " + request);
        }
    }

    private static class FilterChain {
        private List<Filter> filters = new ArrayList<Filter>();
        private Target target;

        void addFilter(Filter filter) {
            filters.add(filter);
        }

        void execute(String request) {
            for (Filter filter : filters) {
                filter.execute(request);
            }
            target.execute(request);
        }

        void setTarget(Target target) {
            this.target = target;
        }
    }

    private static class FilterManager {
        FilterChain filterChain;

        FilterManager(Target target) {
            filterChain = new FilterChain();
            filterChain.setTarget(target);
        }

        void setFilter(Filter filter) {
            filterChain.addFilter(filter);
        }

        void filterRequest(String request) {
            filterChain.execute(request);
        }
    }

    private static class Client {
        FilterManager filterManager;

        void setFilterManager(FilterManager filterManager) {
            this.filterManager = filterManager;
        }

        void sendRequest(String request) {
            filterManager.filterRequest(request);
        }
    }
}
